#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "log.h"
#include "crowbar.h"

//**************************************************

void print_state(StatementList       *statement_list);
//***********
void print_variable(Variable *variable)
{
    logInfo("====================Variable===========================");
    Variable *varPtr = variable;
    /*
     * typedef struct Variable_tag {
    char        *name;
    CRB_Value   value;
    struct Variable_tag *next;
} Variable;
*/
//
    logInfo("print_variable:[%x]",variable );
    while (NULL != varPtr)
    {
        logInfo("[%s]", varPtr->name);
        varPtr = varPtr->next;
    }
    logInfo("====================Variable===END========================");
}

/*
typedef struct {
    CRB_ValueType       type;
    union {
        CRB_Boolean     boolean_value;
        int             int_value;
        double          double_value;
        CRB_String      *string_value;
        CRB_NativePointer       native_pointer;
        CRB_Object      *object;
    } u;
} CRB_Value;
*/
/*
typedef enum {
    CRB_BOOLEAN_VALUE = 1,
    CRB_INT_VALUE,
    CRB_DOUBLE_VALUE,
    CRB_STRING_VALUE,
    CRB_NATIVE_POINTER_VALUE,
    CRB_NULL_VALUE
} CRB_ValueType;
*/
void print_CRB_value(CRB_Value *value)
{
    logInfo1("[CRB_Value]");
    switch(value->type)
    {
        case CRB_BOOLEAN_VALUE:
            logInfo1("[bool][%d]", value->u.boolean_value);
        break;
        case CRB_INT_VALUE:
            logInfo1("[int][%d]", value->u.int_value);
        break;
        case CRB_DOUBLE_VALUE:
            logInfo1("[double][%lf]", value->u.double_value);
        break;
        case CRB_STRING_VALUE:
            logInfo1("[string][%s]", value->u.string_value->string);
        break;
        case CRB_NATIVE_POINTER_VALUE:
            logInfo1("[native_pointer][%s]", value->u.native_pointer.info->name);
        break;
        case CRB_NULL_VALUE:
            logInfo1("[null]");
        break;
        default:
            logInfo1("[type no]");
        break;
    }

}
void print_variable1(Variable *variable)
{
    if (NULL == variable)
    {
        logInfo("[NULL]");
        return;
    }
    Variable *varPtr = variable;
    /*
     * typedef struct Variable_tag {
    char        *name;
    CRB_Value   value;
    struct Variable_tag *next;
} Variable;
*/
//
    logInfo1("[%s]", varPtr->name);
    print_CRB_value(&variable->value);
    logInfo("");
    //CRB_Value


}
void print_fun(FunctionDefinition  *function_list)
{
/*
 * typedef enum {
    CROWBAR_FUNCTION_DEFINITION = 1,
    NATIVE_FUNCTION_DEFINITION
} FunctionDefinitionType;

typedef struct FunctionDefinition_tag {
    char                *name;
    FunctionDefinitionType      type;
    union {
        struct {
            ParameterList       *parameter;
            Block               *block;
        } crowbar_f;
        struct {
            CRB_NativeFunctionProc      *proc;
        } native_f;
    } u;
    struct FunctionDefinition_tag       *next;
} FunctionDefinition;
*/
    logInfo("====================FunctionDefinition===========================");
    FunctionDefinition *funPtr = function_list;
    while(NULL != funPtr)
    {
        logInfo1("[%s][%d]", funPtr->name, funPtr->type);
        if (1 == funPtr->type)
        {
            ParameterList *parameterPtr = funPtr->u.crowbar_f.parameter;
             logInfo1("{");
            while(NULL != parameterPtr)
            {
               logInfo1("%s,", parameterPtr->name);
                parameterPtr = parameterPtr->next;
            }
             logInfo1("}");

        }
        else
        {

        }
        logInfo1("\n");
        funPtr = funPtr->next;
    }
    logInfo("====================FunctionDefinition===END========================");
}
/*
void print_fun(FunctionDefinition  *function_list)
{
    logInfo("====================Variable===========================");
    logInfo("====================Variable===END========================");
}
*/
/*

typedef enum {
    BOOLEAN_EXPRESSION = 1,
    INT_EXPRESSION,
    DOUBLE_EXPRESSION,
    STRING_EXPRESSION,
    IDENTIFIER_EXPRESSION,
    ASSIGN_EXPRESSION,
    ADD_EXPRESSION,
    SUB_EXPRESSION,
    MUL_EXPRESSION,
    DIV_EXPRESSION,
    MOD_EXPRESSION,
    EQ_EXPRESSION,
    NE_EXPRESSION,
    GT_EXPRESSION,
    GE_EXPRESSION,
    LT_EXPRESSION,
    LE_EXPRESSION,
    LOGICAL_AND_EXPRESSION,
    LOGICAL_OR_EXPRESSION,
    MINUS_EXPRESSION,
    FUNCTION_CALL_EXPRESSION,
    NULL_EXPRESSION,
    EXPRESSION_TYPE_COUNT_PLUS_1
} ExpressionType;
*/
static char expressionTypeStr[][64] =
{
    "0",
    "BOOLEAN_EXPRESSION",
    "INT_EXPRESSION",
    "DOUBLE_EXPRESSION",
    "STRING_EXPRESSION",
    "IDENTIFIER_EXPRESSION",
    "ASSIGN_EXPRESSION",
    "ADD_EXPRESSION",
    "SUB_EXPRESSION",
    "MUL_EXPRESSION",
    "DIV_EXPRESSION",
    "MOD_EXPRESSION",
    "EQ_EXPRESSION",
    "NE_EXPRESSION",
    "GT_EXPRESSION",
    "GE_EXPRESSION",
    "LT_EXPRESSION",
    "LE_EXPRESSION",
    "LOGICAL_AND_EXPRESSION",
    "LOGICAL_OR_EXPRESSION",
    "MINUS_EXPRESSION",
    "FUNCTION_CALL_EXPRESSION",
    "NULL_EXPRESSION",
    "EXPRESSION_TYPE_COUNT_PLUS_1",
};
/*
struct Expression_tag {
    ExpressionType type;
    int line_number;
    union {
        CRB_Boolean             boolean_value;
        int                     int_value;
        double                  double_value;
        char                    *string_value;
        char                    *identifier;
        AssignExpression        assign_expression;
        BinaryExpression        binary_expression;
        Expression              *minus_expression;
        FunctionCallExpression  function_call_expression;
    } u;
};
typedef struct {
    char        *variable;
    Expression  *operand;
} AssignExpression;

typedef struct {
    Expression  *left;
    Expression  *right;
} BinaryExpression;

typedef struct {
    char                *identifier;
    ArgumentList        *argument;
} FunctionCallExpression;
*/
void print_expression(Expression *expression)
{
    logInfo1("[%s]", expressionTypeStr[expression->type], expression->line_number);
    int type = expression->type;
    if (ASSIGN_EXPRESSION == type)
    {

        logInfo1("[%s]\n", expression->u.assign_expression.variable);
        print_expression(expression->u.assign_expression.operand);
    }
    else if (FUNCTION_CALL_EXPRESSION == type)
    {
        /*
typedef struct {
    char                *identifier;
    ArgumentList        *argument;
} FunctionCallExpression;
*/
        logInfo1("[%s]", expression->u.function_call_expression.identifier);
        ArgumentList        *argument = expression->u.function_call_expression.argument;
        while (NULL != argument)
        {
            print_expression(argument->expression);
            logInfo1("   ");
            argument = argument->next;
        }

    }
    switch(type)
    {
        case BOOLEAN_EXPRESSION:
            logInfo1("[%d]", expression->u.boolean_value);
            break;
        case INT_EXPRESSION:
            logInfo1("[%d]", expression->u.boolean_value);
            break;
        case DOUBLE_EXPRESSION:
            logInfo1("[%f]", expression->u.double_value);
            break;
        case IDENTIFIER_EXPRESSION:
            logInfo1("[%s]", expression->u.identifier);
            break;
        case STRING_EXPRESSION:
            logInfo1("[%s]", expression->u.string_value);
            break;
        case ADD_EXPRESSION:
        logInfo1("\n[left:]");
            print_expression(expression->u.binary_expression.left);
            logInfo1("\n[right:]");
            print_expression(expression->u.binary_expression.right);
            break;
        case SUB_EXPRESSION:
            break;
        case MUL_EXPRESSION:
            break;
        case DIV_EXPRESSION:
            break;
        case MOD_EXPRESSION:
            break;
        case EQ_EXPRESSION:
            break;
        case NE_EXPRESSION:
            break;
        case GT_EXPRESSION:
            break;
        case GE_EXPRESSION:
            break;
        case LT_EXPRESSION:
            break;
        case LE_EXPRESSION:
            break;
        case LOGICAL_AND_EXPRESSION:
            break;
        case LOGICAL_OR_EXPRESSION:
            break;
        case MINUS_EXPRESSION:
            break;
        case NULL_EXPRESSION:
            break;
    }

}
/*
typedef struct {
    Expression  *condition;
    Block       *then_block;
    Elsif       *elsif_list;
    Block       *else_block;
} IfStatement;
*/
void print_ifStatement(IfStatement *statement)
{
    logInfo1("\n[if:]");
    print_expression(statement->condition);
    print_state(statement->then_block->statement_list);
}
 /*
  * typedef enum {
    EXPRESSION_STATEMENT = 1,
    GLOBAL_STATEMENT,
    IF_STATEMENT,
    WHILE_STATEMENT,
    FOR_STATEMENT,
    RETURN_STATEMENT,
    BREAK_STATEMENT,
    CONTINUE_STATEMENT,
    STATEMENT_TYPE_COUNT_PLUS_1
} StatementType;
 */
static char statementTypeStr[][64] =
{
    "0",
    "EXPRESSION_STATEMENT",
    "GLOBAL_STATEMENT",
    "IF_STATEMENT",
    "WHILE_STATEMENT",
    "FOR_STATEMENT",
    "RETURN_STATEMENT",
    "BREAK_STATEMENT",
    "CONTINUE_STATEMENT",
    "STATEMENT_TYPE_COUNT_PLUS_1"
};
void print_state(StatementList       *statement_list)
{
/*
 * typedef struct StatementList_tag {
    Statement   *statement;
    struct StatementList_tag    *next;
} StatementList;

struct Statement_tag {
    StatementType       type;
    int                 line_number;
    union {
        Expression      *expression_s;
        GlobalStatement global_s;
        IfStatement     if_s;
        WhileStatement  while_s;
        ForStatement    for_s;
        ReturnStatement return_s;
    } u;
};
 */


   // logInfo("====================StatementList===========================");
    StatementList *statementPtr = statement_list;
    while(NULL != statementPtr)
    {
        int type = statementPtr->statement->type;
        logInfo1("\n[%d:][state=%s]", statementPtr->statement->line_number, statementTypeStr[type]);

        if (EXPRESSION_STATEMENT == type)
        {
            print_expression(statementPtr->statement->u.expression_s);
        }
        else
        {
            print_ifStatement(&statementPtr->statement->u.if_s);
        }
        statementPtr = statementPtr->next;
    }
    logInfo1("\n");
   // logInfo("\n====================StatementList===END========================");
}

//struct CRB_Interpreter_tag;
void print_interpreter(struct CRB_Interpreter_tag *interpreter)
{
/*
 * struct CRB_Interpreter_tag {
    MEM_Storage         interpreter_storage;
    MEM_Storage         execute_storage;
    Variable            *variable;
    FunctionDefinition  *function_list;
    StatementList       *statement_list;
    int                 current_line_number;
};
 */
    logInfo("======================CRB_Interpreter=========================");
    logInfo("[%x][%x][%x][%x][%x][%d]", interpreter->interpreter_storage, interpreter->execute_storage,
        interpreter->variable, interpreter->function_list, interpreter->statement_list, interpreter->current_line_number);
    print_variable(interpreter->variable);
    print_fun(interpreter->function_list);
    print_state(interpreter->statement_list);
    logInfo("======================CRB_Interpreter====END=====================");
}




